/**
 * 
 */
package com.zte.claa.inficombo.csa.app.service.rptparse.ext.comm;

import java.nio.charset.Charset;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zte.claa.inficombo.csa.app.service.rptparse.ext.comm.mina.MinaConnManager;
import com.zte.claa.inficombo.csa.app.service.rptparse.ext.comm.mina.msgbean.MinaCommRequest;
import com.zte.claa.inficombo.csa.app.service.rptparse.ext.comm.mina.msgbean.MinaCommResponse;

/**
 * @author lyp
 *
 */

public class CommServiceImpl implements CommService {
	// 日志打印.
	private Logger loger = LoggerFactory.getLogger(CommServiceImpl.class);
	
	private CommParamProps commProps;
	
	// 字符集
	private Charset cs = null;
	
	// mina底层链路管理器.
	private MinaConnManager minaConnManager = null;
	
	// 同步命令执行上下文.
	private ReqExecContext execContext = new ReqExecContext();
	
	/**
	 * 构建器.
	 * 
	 * @param CommProps
	 */
	public CommServiceImpl(CommParamProps commProps){
		this.commProps = commProps;
	}
	
	/**
	 * 
	 * @return
	 */
	public Charset getCharset(){		
		if(this.cs == null){
			this.cs = Charset.forName(this.commProps.getCharsetname());
		}
		return cs;
	}
	
	/* (non-Javadoc)
	 * @see com.zte.claa.infiboss.dataaccess.bossinfcomm.IBossInfCommService#execCommand(java.lang.String)
	 */
	@Override
	public CommParseResult execCommand(MinaCommRequest req) throws Exception {
		if(this.minaConnManager == null){
			this.connectToDestSvr(false);
		}		
		loger.info("Begin to exec command: "+req);		
		this.execContext.resetContext();
		this.execContext.setReq(req);
		this.minaConnManager.sendCommand(req);
		this.waitForResult(this.commProps.getCmdtimeoutsecond() * 1000L);
		String rspMsg = this.execContext.getRspMsg();
		// 命令响应正常.
		if(rspMsg != null){
			loger.debug("Command rsp: "+rspMsg);
			CommParseResult ret = new CommParseResult();
			ret.setReq(req);
			ret.setRsp(new MinaCommResponse(rspMsg));
			return ret;
		}
		String err = "命令执行失败！";
		Throwable t = this.execContext.getRetErr();
		if(t != null){
			loger.error("Command exec failed: "+t.getMessage(), t);
			err = t.getMessage();
		}
		throw new Exception(err);
	}
	
	/**
	 * 执行命令不关注响应.
	 * 
	 * @param jsonCmd
	 * @return 命令响应的string
	 * @throws Exception
	 */
	public void execCommandIngoreRsp(MinaCommRequest req) throws Exception {
		if(this.minaConnManager == null){
			this.connectToDestSvr(false);
		}
		loger.info("Begin to exec command: "+req);		
		this.minaConnManager.sendCommand(req);
		loger.info("Command is sent to destsvr: "+this.commProps.getSvrip()+":"+this.commProps.getPort());
	}
	
	/**
	 * 等待执行结果返回。
	 * @param waittime
	 * @throws Exception
	 */
	private void waitForResult(long waittime) throws Exception {
		synchronized(this.execContext){
			if(this.execContext.isExecFinished()){
				return;
			}
			this.execContext.wait(waittime);
		}
	}

	/* (non-Javadoc)
	 * @see com.zte.claa.inficombo.apigwv1.app.framework.service.iotm.IBossInfCommService#connectToIotm()
	 */
	@Override
	public void connectToDestSvr() throws Exception {
		this.connectToDestSvr(false);
	}
	
	/**
	 * 
	 * @param isAutoReconnect
	 * @throws Exception
	 */
	private synchronized void connectToDestSvr(boolean isAutoReconnect) throws Exception {
		if(this.minaConnManager != null){
			try{
				this.minaConnManager.releaseConnection();
				this.minaConnManager = null;
			}catch(Exception e){
				loger.warn(e.getMessage());
			}
		}
		this.minaConnManager = new MinaConnManager(this.commProps, this);
		try{
			this.minaConnManager.createConnect();
		}catch(Exception ex){
			this.minaConnManager = null;
			throw ex;
		}
		loger.info("connectToDestSvr ok: "+this.commProps.getSvrip()+":"+this.commProps.getPort());
	}

	/* (non-Javadoc)
	 * @see com.zte.claa.inficombo.apigwv1.app.framework.service.iotm.IBossInfCommService#closeConnectToIotm()
	 */
	@Override
	public synchronized void closeConnectToDestSvr() {
		// 关闭链路》
		if(this.minaConnManager == null){
			return;
		}
		try{
			this.minaConnManager.releaseConnection();			
			loger.warn("closeConnectToDestSvr ok: "+this.commProps.getSvrip()+":"+this.commProps.getPort());
		}catch(Exception e){
			loger.warn(e.getMessage());
		}finally{
			this.minaConnManager = null;
		}
	}

	/* (non-Javadoc)
	 * @see com.zte.claa.inficombo.apigwv1.app.framework.service.iotm.IBossInfCommService#reportMessage(java.lang.String)
	 */
	@Override
	public void reportMessage(String msg) {
		loger.info("Response message: "+msg);
		this.execContext.setRetMessage(msg);
		synchronized(this.execContext){
			this.execContext.notifyAll();
		}
	}

	/* (non-Javadoc)
	 * @see com.zte.claa.inficombo.apigwv1.app.framework.service.iotm.IotmCommService#reportException(java.lang.Throwable)
	 */
	@Override
	public void reportException(Throwable cause) {
		this.execContext.setRetErr(cause);
		synchronized(this.execContext){
			this.execContext.notifyAll();
		}
		loger.warn("reportException: "+cause.getMessage());
	}

	/* (non-Javadoc)
	 * @see com.zte.claa.inficombo.apigwv1.app.framework.service.iotm.IotmCommService#reportConnectStatus(int)
	 */
	@Override
	public void reportConnectStatus(int status) {
		if(status == CommService.CONN_STATUS_IDLE){
			// 如果长时间空闲，则关闭链路.
			this.closeConnectToDestSvr();
		}
		if(status == CommService.CONN_STATUS_CLOSE){
			// session关闭，也关闭链路.
			this.closeConnectToDestSvr();
		}
	}

	/* (non-Javadoc)
	 * @see com.zte.claa.inficombo.apigwv1.app.framework.service.iotm.IotmCommService#hasConnectToIotm()
	 */
	@Override
	public boolean hasConnectToDestSvr() {
		if(this.minaConnManager == null){
			return false;
		}
		return true;
	}

}
